package com.github.bryx.workflow.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.bryx.workflow.domain.*;
import com.github.bryx.workflow.dto.runtime.QuerySubworkflowInstanceDto;
import com.github.bryx.workflow.dto.runtime.QueryWorkflowTaskInstanceDto;
import com.github.bryx.workflow.util.CollectionsUtil;
import com.google.common.collect.Lists;
import org.springframework.lang.Nullable;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Author jameswu
 * @Date 2021/6/10
 **/
public interface WorkflowRuntimeQuery {

    public WorkflowInstance getWorkflowInstanceById(String workflowInstanceId);

    public String getProcessDefKeyOfWorkflowInstance(String workflowInstanceId);

    public WorkflowTaskInstance getWorkflowTaskInstanceById(String workflowInstanceTaskId);

    public Page<WorkflowTaskInstance> queryWorkflowTaskInstances(QueryWorkflowTaskInstanceDto<WorkflowTaskInstance> dto);

    default public List<WorkflowTaskInstance> getWorkflowTaskInstanceByIds(List<String> workflowTaskInstanceIds){
        return this.queryWorkflowTaskInstances(QueryWorkflowTaskInstanceDto.<WorkflowTaskInstance>builder()
                .workflowTaskInstanceIds(workflowTaskInstanceIds)
                .build()).getRecords();
    }

    default public List<WorkflowTaskInstance> getWorkflowTaskInstances(String workflowInstanceId){
        return this.queryWorkflowTaskInstances(QueryWorkflowTaskInstanceDto.<WorkflowTaskInstance>builder()
                .workflowInstanceIds(Lists.newArrayList(workflowInstanceId))
                .build()).getRecords();
    }

    default public List<WorkflowTaskInstance> getRunningWorkflowTaskInstances(String workflowInstanceId){
        return Optional.ofNullable(this.queryRunningWorkflowTaskInstances(Lists.newArrayList(workflowInstanceId)).get(workflowInstanceId)).orElse(Lists.newArrayList());
    }

    default public Map<String, List<WorkflowTaskInstance>> queryRunningWorkflowTaskInstances(List<String> workflowInstanceIds){
        QueryWorkflowTaskInstanceDto<WorkflowTaskInstance> queryTaskDto = new QueryWorkflowTaskInstanceDto();
        queryTaskDto.setStatuses(Lists.newArrayList(WorkflowTaskInstance.WorkflowTaskInstanceStatus.RUNNING));
        queryTaskDto.setWorkflowInstanceIds(workflowInstanceIds);
        Page<WorkflowTaskInstance> workflowTaskInstancePage = this.queryWorkflowTaskInstances(queryTaskDto);
        return workflowTaskInstancePage.getRecords().stream().collect(Collectors.groupingBy(WorkflowTaskInstance::getWorkflowInstanceId));
    }

    default public @Nullable WorkflowTaskInstance getRecentHistoricalWorkflowTaskInstance(String taskDefId){
        List<WorkflowTaskInstance> records = this.queryWorkflowTaskInstances(QueryWorkflowTaskInstanceDto.<WorkflowTaskInstance>builder()
                .taskDefIds(Lists.newArrayList(taskDefId))
                .statuses(Lists.newArrayList(WorkflowTaskInstance.WorkflowTaskInstanceStatus.COMPLETED))
                .orderField(WorkflowTaskInstance::getEndTime)
                .asc(false)
                .build()).getRecords();
        if (CollectionsUtil.isNotEmpty(records)){
            return records.get(0);
        }
        return null;
    }

    public List<WorkflowTimerJob> getWorkflowTimerJobsOnTask(String workflowInstanceTaskId);

    public List<WorkflowTimerJob> getWorkflowTimerJobsOnWorkflow(String workflowInstanceId);

    public WorkflowTimerJob getWorkflowTimerByJobId(String workflowTimerJobId);

    public List<WorkflowTimerInstance> getWorkflowTimerInstancesOnTask(String workflowInstanceTaskId);

    List<WorkflowInstance> querySubworkflowInstances(QuerySubworkflowInstanceDto querySubworkflowInstanceDto);

    List<WorkflowInstanceActivity> queryWorkflowInstActivity(String workflowInstanceId);
}
